package com.yanqu.road.server.gameplayer.module.verification;

import com.yanqu.road.entity.activity.washe.config.WasheConfig;
import com.yanqu.road.entity.activity.washe.data.WasheUserData;
import com.yanqu.road.entity.config.verification.VerificationConfig;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.player.UserVerification;
import com.yanqu.road.entity.player.UserVerificationItem;
import com.yanqu.road.entity.player.UserVerificationItemQA;
import com.yanqu.road.logic.bussiness.verification.VerificationBusiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.pb.verification.VerificationProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.washe.WasheModule;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.manger.ServerLanguageMgr;
import com.yanqu.road.server.manger.activity.washe.WasheMgr;
import com.yanqu.road.server.manger.config.VerificationConfigMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.LocalDateTimeHelper;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.config.Config;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 人机验证模块
 */
public class VerificationModule extends GeneralModule {

    private RandomHelper randomHelper = new RandomHelper();

    private UserVerification userVerification;

    public VerificationModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        userVerification = VerificationBusiness.getUserVerification(player.getUserId());
        if (userVerification == null) {
            userVerification = new UserVerification();
            userVerification.setUserId(player.getUserId());
            userVerification.setVerificationItemMap(new ConcurrentHashMap<>());
            userVerification.setResetTime(LocalDateTimeHelper.getZeroTimeTimeStamp());
            userVerification.setInsertOption();
        }
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if (userVerification != null) {
            if (userVerification.isInsertOption()) {
                VerificationBusiness.addUserVerification(userVerification);
            } else if (userVerification.isUpdateOption()) {
                VerificationBusiness.updateUserVerification(userVerification);
            }
        }
        return true;
    }

    /**
     * 根据系统id获取验证信息
     *
     * @param systemId 系统id
     */
    public UserVerificationItem getUserVerificationItem(int systemId) {
        if (!userVerification.getVerificationItemMap().containsKey(systemId)) {
            userVerification.getVerificationItemMap().put(systemId, new UserVerificationItem());
            userVerification.setUpdateOption();
        }
        return userVerification.getVerificationItemMap().get(systemId);
    }

    /**
     * 是否需要验证
     *
     * @param systemId 系统id
     */
    public boolean needVerification(int systemId) {
        boolean needVerification = false;
        UserVerificationItem verificationItem = getUserVerificationItem(systemId);
        if (systemId == eSystemId.WasheActivity.getValue()) {
            // 判断下是否达到人机验证条件
            WasheConfig washeConfig = WasheMgr.getWasheConfig();
            if (washeConfig == null) {
                return false;
            }
            WasheUserData washeUserData = player.getModule(WasheModule.class).getWasheUserData();
            if (washeUserData == null) {
                return false;
            }
            for (Map.Entry<Integer, Integer> entry : verificationItem.getConditionMap().entrySet()) {
                int type = entry.getKey();
                int cnt = entry.getValue();
                if ((type == 1 && cnt >= washeConfig.getWaiGuaCheckCondition1())
                        || (type == 2 && cnt >= washeConfig.getWaiGuaCheckCondition2())
                        || (type == 3 && cnt >= washeConfig.getWaiGuaCheckCondition3())) {
                    needVerification = true;
                    break;
                }
            }
        }
        return needVerification;
    }

    /**
     * 推送验证信息
     */
    public void verificationDatasync(int systemId) {
        UserVerificationItem verificationItem = getUserVerificationItem(systemId);
        // 获取验证信息
        UserVerificationItemQA itemQA = verificationItem.getItemQA();
        long nowTime = System.currentTimeMillis();
        // 没有验证信息重新获取信息视为上次的验证失败，尝试次数+1
        if (needVerification(systemId) && (itemQA.getQuestionId() == 0 || nowTime >= verificationItem.getForbiddenTime() && nowTime >= itemQA.getVerificationTime())) {
            if (itemQA.getQuestionId() != 0) {
                verificationItem.setFailureTimes(verificationItem.getFailureTimes() + 1);
            }
            // 生成验证
            genVerification(systemId);
            userVerification.getVerificationItemMap().put(systemId, verificationItem);
            userVerification.setUpdateOption();
        }
        VerificationProto.VerificationDataSyncMsg.Builder respMsg = VerificationProto.VerificationDataSyncMsg.newBuilder();
        respMsg.setSystemId(systemId);
        respMsg.setVerification(parseVerificationTempMsg(verificationItem));
        player.sendPacket(Protocol.U_VERIFICATION_DATA_SYNC, respMsg);
    }

    /**
     * 生成验证信息
     *
     * @param systemId 系统id
     */
    public void genVerification(int systemId) {
        UserVerificationItem verificationItem = getUserVerificationItem(systemId);
        UserVerificationItemQA itemQA = verificationItem.getItemQA();
        VerificationConfig verificationConfig = VerificationConfigMgr.randomGetVerification(systemId);
        if (verificationConfig != null) {
            int questionId = verificationConfig.getId();
            itemQA.setQuestionId(questionId);
            List<Integer> answerIdList = StringUtils.stringToIntegerList(verificationConfig.getAnswer(), "\\|");
            List<Integer> configAnswerId = StringUtils.stringToIntegerList(GameConfig.ROBOT_CHECK_1_ANSWER_DATA, "\\|");
            answerIdList.removeIf(id -> !configAnswerId.contains(id));
            int answerId = answerIdList.get(randomHelper.next(0, answerIdList.size()));
            itemQA.setAnswerId(answerId);
            // 随机下剩下的选项
            List<Integer> chooseIdList = VerificationConfigMgr.randomGetChooseIdList(systemId, questionId, GameConfig.ROBOT_CHECK_1_ANSWER_NUM - 1);
            chooseIdList.add(answerId);
            Collections.shuffle(chooseIdList);
            itemQA.setChooseIdList(chooseIdList);
            // 获取有效期
            itemQA.setVerificationTime(System.currentTimeMillis() + getWaitTime(systemId) * DateHelper.SECOND_MILLIONS);
            // 验证奖励
            itemQA.setReward(getVerificationReward(systemId));
        }
    }

    private long getWaitTime(int systemId) {
        long waitTime = 0;
        if (systemId == eSystemId.WasheActivity.getValue()) {
            // 瓦舍夺魁
            WasheConfig washeConfig = WasheMgr.getWasheConfig();
            if (washeConfig == null) {
                return 0;
            }
            WasheUserData washeUserData = player.getModule(WasheModule.class).getWasheUserData();
            if (washeUserData == null) {
                return 0;
            }
            waitTime = washeConfig.getWaiGuaCheckWaitTime();
        }
        return waitTime;
    }

    public String getVerificationReward(int systemId) {
        String reward = "";
        if (systemId == eSystemId.WasheActivity.getValue()) {
            // 瓦舍夺魁
            WasheConfig washeConfig = WasheMgr.getWasheConfig();
            if (washeConfig == null) {
                return "";
            }
            WasheUserData washeUserData = player.getModule(WasheModule.class).getWasheUserData();
            if (washeUserData == null) {
                return "";
            }
            reward = washeConfig.getWaiGuaCheckReward();
        }
        return reward;
    }


    public VerificationProto.VerificationTempMsg.Builder parseVerificationTempMsg(UserVerificationItem verificationItem) {
        VerificationProto.VerificationTempMsg.Builder builder = VerificationProto.VerificationTempMsg.newBuilder();
        UserVerificationItemQA itemQA = verificationItem.getItemQA();
        int questionId = itemQA.getQuestionId();
        if (questionId != 0) {
            VerificationConfig config = VerificationConfigMgr.getVerificationConfig(questionId);
            builder.setQuestion(ServerLanguageMgr.getContent(config.getQuestion(), player.getLanguage()));
            builder.addAllChooseIdList(itemQA.getChooseIdList());
            builder.setVerificationTime(itemQA.getVerificationTime());
            builder.setReward(itemQA.getReward());
        }
        builder.setForbiddenTime(verificationItem.getForbiddenTime());
        return builder;
    }

    /**
     * 校验验证信息
     * @param systemId 系统id
     * @param answerId 答案id
     */
    public int checkVerificationData(int systemId, int answerId) {
        UserVerificationItem verificationItem = getUserVerificationItem(systemId);
        UserVerificationItemQA itemQA = verificationItem.getItemQA();
        long nowTime = System.currentTimeMillis();
        // 已被禁用无需验证
        if (nowTime < verificationItem.getForbiddenTime()) {
            return GameErrorCode.E_VERIFICATION_HAD_FORBIDDEN;
        }
        // 人机验证允许玩家尝试次数
        int tryNum = 3;
        if (systemId == eSystemId.WasheActivity.getValue()) {
            // 瓦舍夺魁
            WasheConfig washeConfig = WasheMgr.getWasheConfig();
            if (washeConfig == null) {
                return GameErrorCode.E_WASHE_NO_SYSTEM;
            }
            WasheUserData washeUserData = player.getModule(WasheModule.class).getWasheUserData();
            if (washeUserData == null) {
                return GameErrorCode.E_SYSTEM_NO_OPEN;
            }
            tryNum = washeConfig.getWaiGuaCheckTryNum();
        } else {
            return GameErrorCode.E_VERIFICATION_SYSTEM_NOT_OPEN;
        }
        VerificationProto.CheckVerificationDataRespMsg.Builder respMsg = VerificationProto.CheckVerificationDataRespMsg.newBuilder();
        int verificationResult = 0;
        if (answerId == -1 || nowTime > itemQA.getVerificationTime()) {
            // 过期了,没通过
            verificationResult = GameErrorCode.E_VERIFICATION_OVER_TIME;
        } else if (!itemQA.getChooseIdList().contains(answerId) || itemQA.getAnswerId() != answerId) {
            // 验证失败
            verificationResult = GameErrorCode.E_VERIFICATION_NO_PASS;
        }
        // 验证失败处理
        if (verificationResult != 0) {
            // 验证次数+1
            verificationItem.setFailureTimes(verificationItem.getFailureTimes() + 1);
            if (Config.isDebug()) {
                log.info("【人机验证】用户id:{},系统id:{},验证失败,验证失败次数:{}", player.getUserId(), systemId, verificationItem.getFailureTimes());
            }
            if (verificationItem.getFailureTimes() >= tryNum) {
                // 多次验证
                verificationResult =  GameErrorCode.E_VERIFICATION_CHECK_TIME_LIMIT;
                // 未通过，禁止游戏
                verificationItem.setNoPassTimes(verificationItem.getNoPassTimes() + 1);
                // 清空相关数据
                verificationItem.setFailureTimes(0);
                verificationItem.setConditionMap(new HashMap<>());
                verificationItem.setItemQA(new UserVerificationItemQA());
                addPunishTime(systemId, verificationItem);
            } else {
                // 生成新验证
                genVerification(systemId);
            }
        } else {
            // 通过验证
            verificationItem.setFailureTimes(0);
            // 清空条件计数
            verificationItem.setConditionMap(new HashMap<>());
            verificationItem.setItemQA(new UserVerificationItemQA());
            verificationItem.setForbiddenTime(0);
            // 获得验证通过奖励
            String reward = itemQA.getReward();
            if (StringUtils.isNullOrEmpty(reward)) {
                player.getModule(CurrencyModule.class).addCurrency(PropertyHelper.parseStringToProperty(reward), eLogMoneyType.System, eLogMoneyType.Verification);
            }
            respMsg.setReward(reward);
        }
        userVerification.getVerificationItemMap().put(systemId, verificationItem);
        userVerification.setUpdateOption();
        respMsg.setRet(verificationResult);
        respMsg.setVerification(parseVerificationTempMsg(verificationItem));
        player.sendPacket(Protocol.U_CHECK_VERIFICATION_DATA, respMsg);
        return 0;
    }

    /**
     * 增加禁止时间
     * @param systemId 系统id
     */
    private void addPunishTime(int systemId, UserVerificationItem verificationItem) {
        if (systemId == eSystemId.WasheActivity.getValue()) {
            WasheConfig washeConfig = WasheMgr.getWasheConfig();
            if (washeConfig == null) {
                return;
            }
            long addPunishTime = 0;
            List<String> punishTimeList = StringUtils.stringToStringList(washeConfig.getWaiGuaCheckPunishTime(), "\\|");
            for (String s : punishTimeList) {
                String[] split = s.split(";");
                if (verificationItem.getNoPassTimes() >= Integer.parseInt(split[0])) {
                    addPunishTime = Long.parseLong(split[1]);
                }
            }
            verificationItem.setForbiddenTime(Math.max(System.currentTimeMillis(), verificationItem.getForbiddenTime()) + addPunishTime * DateHelper.SECOND_MILLIONS);
            if (Config.isDebug()) {
                log.info("【人机验证】用户id:{},系统id:{},增加禁用时间:{}s,解除禁用时间:{}", player.getUserId(), systemId, addPunishTime, verificationItem.getForbiddenTime());
            }
        }
    }

    /**
     * 参数上传
     *
     * @param systemId      系统id
     * @param conditionType 条件类型
     * @param param         参数
     */
    public int uploadParam(int systemId, int conditionType, String param) {
        if (systemId == eSystemId.WasheActivity.getValue()) {
            // 玩家点击选择优伶卡时的位置坐标，坐标相同次数+1
            if (conditionType == 1) {
                addConditionCount(systemId, conditionType, 1);
            }
        }
        return 0;
    }

    /**
     * 添加条件计数
     */
    public void addConditionCount(int systemId, int conditionType, int addCount) {
        UserVerificationItem verificationItem = getUserVerificationItem(systemId);
        Map<Integer, Integer> conditionMap = verificationItem.getConditionMap();
        conditionMap.put(conditionType, conditionMap.getOrDefault(conditionType, 0) + addCount);
        verificationItem.setConditionMap(conditionMap);
        userVerification.setUpdateOption();
    }

    /**
     * 是否能玩
     * @param systemId 系统id
     */
    public boolean canPlay(int systemId) {
        return !needVerification(systemId) && getUserVerificationItem(systemId).getForbiddenTime() < System.currentTimeMillis();
    }


    public void resetOneDay() {
        long zeroTime = LocalDateTimeHelper.getZeroTimeTimeStamp();
        if (userVerification.getResetTime() < zeroTime) {
            userVerification.setResetTime(zeroTime);
            for (Map.Entry<Integer, UserVerificationItem> entry : userVerification.getVerificationItemMap().entrySet()) {
                entry.getValue().setNoPassTimes(0);
                entry.getValue().setFailureTimes(0);
                entry.getValue().setItemQA(new UserVerificationItemQA());
                entry.getValue().setConditionMap(new HashMap<>());
            }
            userVerification.setUpdateOption();
        }
    }

    public UserVerification getUserVerification() {
        return userVerification;
    }
}
